New upstream version 18.0.1+dfsg1

This commit is contained in:
Sebastian Ramacher 2017-04-19 21:54:15 +02:00
parent 6efda2859e
commit f2cf6cce50
1337 changed files with 41178 additions and 84670 deletions

View file

@ -14,6 +14,7 @@ set(libobs-d3d11_SOURCES
d3d11-texture2d.cpp
d3d11-vertexbuffer.cpp
d3d11-duplicator.cpp
d3d11-rebuild.cpp
d3d11-zstencilbuffer.cpp)
set(libobs-d3d11_HEADERS

View file

@ -20,20 +20,9 @@
static inline bool get_monitor(gs_device_t *device, int monitor_idx,
IDXGIOutput **dxgiOutput)
{
ComPtr<IDXGIAdapter> dxgiAdapter;
ComPtr<IDXGIDevice> dxgiDevice;
HRESULT hr;
hr = device->device->QueryInterface(__uuidof(IDXGIDevice),
(void**)dxgiDevice.Assign());
if (FAILED(hr))
throw HRError("Failed to query IDXGIDevice", hr);
hr = dxgiDevice->GetAdapter(dxgiAdapter.Assign());
if (FAILED(hr))
throw HRError("Failed to get adapter", hr);
hr = dxgiAdapter->EnumOutputs(monitor_idx, dxgiOutput);
hr = device->adapter->EnumOutputs(monitor_idx, dxgiOutput);
if (FAILED(hr)) {
if (hr == DXGI_ERROR_NOT_FOUND)
return false;
@ -44,14 +33,13 @@ static inline bool get_monitor(gs_device_t *device, int monitor_idx,
return true;
}
gs_duplicator::gs_duplicator(gs_device_t *device_, int monitor_idx)
: texture(nullptr), device(device_)
void gs_duplicator::Start()
{
ComPtr<IDXGIOutput1> output1;
ComPtr<IDXGIOutput> output;
HRESULT hr;
if (!get_monitor(device, monitor_idx, output.Assign()))
if (!get_monitor(device, idx, output.Assign()))
throw "Invalid monitor index";
hr = output->QueryInterface(__uuidof(IDXGIOutput1),
@ -64,6 +52,14 @@ gs_duplicator::gs_duplicator(gs_device_t *device_, int monitor_idx)
throw HRError("Failed to duplicate output", hr);
}
gs_duplicator::gs_duplicator(gs_device_t *device_, int monitor_idx)
: gs_obj (device_, gs_type::gs_duplicator),
texture (nullptr),
idx (monitor_idx)
{
Start();
}
gs_duplicator::~gs_duplicator()
{
delete texture;

View file

@ -19,8 +19,6 @@
void gs_index_buffer::InitBuffer()
{
D3D11_BUFFER_DESC bd;
D3D11_SUBRESOURCE_DATA srd;
HRESULT hr;
memset(&bd, 0, sizeof(bd));
@ -39,7 +37,7 @@ void gs_index_buffer::InitBuffer()
gs_index_buffer::gs_index_buffer(gs_device_t *device, enum gs_index_type type,
void *indices, size_t num, uint32_t flags)
: device (device),
: gs_obj (device, gs_type::gs_index_buffer),
dynamic ((flags & GS_DYNAMIC) != 0),
type (type),
num (num),

View file

@ -0,0 +1,348 @@
/******************************************************************************
Copyright (C) 2016 by Hugh Bailey <obs.jim@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include "d3d11-subsystem.hpp"
inline void gs_vertex_buffer::Rebuild()
{
uvBuffers.clear();
uvSizes.clear();
BuildBuffers();
}
inline void gs_index_buffer::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateBuffer(&bd, &srd, &indexBuffer);
if (FAILED(hr))
throw HRError("Failed to create buffer", hr);
}
void gs_texture_2d::RebuildSharedTextureFallback()
{
td = {};
td.Width = 2;
td.Height = 2;
td.MipLevels = 1;
td.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
td.ArraySize = 1;
td.SampleDesc.Count = 1;
width = td.Width;
height = td.Height;
dxgiFormat = td.Format;
levels = 1;
resourceDesc = {};
resourceDesc.Format = td.Format;
resourceDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceDesc.Texture2D.MipLevels = 1;
isShared = false;
}
inline void gs_texture_2d::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
if (isShared) {
hr = dev->OpenSharedResource((HANDLE)(uintptr_t)sharedHandle,
__uuidof(ID3D11Texture2D), (void**)&texture);
if (FAILED(hr)) {
blog(LOG_WARNING, "Failed to rebuild shared texture: ",
"0x%08lX", hr);
RebuildSharedTextureFallback();
}
}
if (!isShared) {
hr = dev->CreateTexture2D(&td,
data.size() ? srd.data() : nullptr,
&texture);
if (FAILED(hr))
throw HRError("Failed to create 2D texture", hr);
}
hr = dev->CreateShaderResourceView(texture, &resourceDesc, &shaderRes);
if (FAILED(hr))
throw HRError("Failed to create resource view", hr);
if (isRenderTarget)
InitRenderTargets();
if (isGDICompatible) {
hr = texture->QueryInterface(__uuidof(IDXGISurface1),
(void**)&gdiSurface);
if (FAILED(hr))
throw HRError("Failed to create GDI surface", hr);
}
}
inline void gs_zstencil_buffer::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
hr = dev->CreateTexture2D(&td, nullptr, &texture);
if (FAILED(hr))
throw HRError("Failed to create depth stencil texture", hr);
hr = dev->CreateDepthStencilView(texture, &dsvd, &view);
if (FAILED(hr))
throw HRError("Failed to create depth stencil view", hr);
}
inline void gs_stage_surface::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateTexture2D(&td, nullptr, &texture);
if (FAILED(hr))
throw HRError("Failed to create staging surface", hr);
}
inline void gs_sampler_state::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateSamplerState(&sd, state.Assign());
if (FAILED(hr))
throw HRError("Failed to create sampler state", hr);
}
inline void gs_vertex_shader::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
hr = dev->CreateVertexShader(data.data(), data.size(), nullptr, &shader);
if (FAILED(hr))
throw HRError("Failed to create vertex shader", hr);
hr = dev->CreateInputLayout(layoutData.data(), (UINT)layoutData.size(),
data.data(), data.size(), &layout);
if (FAILED(hr))
throw HRError("Failed to create input layout", hr);
if (constantSize) {
hr = dev->CreateBuffer(&bd, NULL, &constants);
if (FAILED(hr))
throw HRError("Failed to create constant buffer", hr);
}
for (gs_shader_param &param : params) {
param.nextSampler = nullptr;
param.curValue.clear();
gs_shader_set_default(&param);
}
}
inline void gs_pixel_shader::Rebuild(ID3D11Device *dev)
{
HRESULT hr;
hr = dev->CreatePixelShader(data.data(), data.size(), nullptr,
&shader);
if (FAILED(hr))
throw HRError("Failed to create pixel shader", hr);
if (constantSize) {
hr = dev->CreateBuffer(&bd, NULL, &constants);
if (FAILED(hr))
throw HRError("Failed to create constant buffer", hr);
}
for (gs_shader_param &param : params) {
param.nextSampler = nullptr;
param.curValue.clear();
gs_shader_set_default(&param);
}
}
inline void gs_swap_chain::Rebuild(ID3D11Device *dev)
{
HRESULT hr = device->factory->CreateSwapChain(dev, &swapDesc, &swap);
if (FAILED(hr))
throw HRError("Failed to create swap chain", hr);
Init();
}
inline void SavedBlendState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateBlendState(&bd, &state);
if (FAILED(hr))
throw HRError("Failed to create blend state", hr);
}
inline void SavedZStencilState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateDepthStencilState(&dsd, &state);
if (FAILED(hr))
throw HRError("Failed to create depth stencil state", hr);
}
inline void SavedRasterState::Rebuild(ID3D11Device *dev)
{
HRESULT hr = dev->CreateRasterizerState(&rd, &state);
if (FAILED(hr))
throw HRError("Failed to create rasterizer state", hr);
}
const static D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
};
void gs_device::RebuildDevice()
try {
ID3D11Device *dev = nullptr;
HRESULT hr;
blog(LOG_WARNING, "Device Remove/Reset! Rebuilding all assets...");
/* ----------------------------------------------------------------- */
gs_obj *obj = first_obj;
while (obj) {
switch (obj->obj_type) {
case gs_type::gs_vertex_buffer:
((gs_vertex_buffer*)obj)->Release();
break;
case gs_type::gs_index_buffer:
((gs_index_buffer*)obj)->Release();
break;
case gs_type::gs_texture_2d:
((gs_texture_2d*)obj)->Release();
break;
case gs_type::gs_zstencil_buffer:
((gs_zstencil_buffer*)obj)->Release();
break;
case gs_type::gs_stage_surface:
((gs_stage_surface*)obj)->Release();
break;
case gs_type::gs_sampler_state:
((gs_sampler_state*)obj)->Release();
break;
case gs_type::gs_vertex_shader:
((gs_vertex_shader*)obj)->Release();
break;
case gs_type::gs_pixel_shader:
((gs_pixel_shader*)obj)->Release();
break;
case gs_type::gs_duplicator:
((gs_duplicator*)obj)->Release();
break;
case gs_type::gs_swap_chain:
((gs_swap_chain*)obj)->Release();
break;
}
obj = obj->next;
}
for (auto &state : zstencilStates)
state.Release();
for (auto &state : rasterStates)
state.Release();
for (auto &state : blendStates)
state.Release();
context->ClearState();
context.Release();
device.Release();
adapter.Release();
factory.Release();
/* ----------------------------------------------------------------- */
InitFactory(adpIdx);
uint32_t createFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, createFlags, featureLevels,
sizeof(featureLevels) / sizeof(D3D_FEATURE_LEVEL),
D3D11_SDK_VERSION, &device, nullptr, &context);
if (FAILED(hr))
throw HRError("Failed to create device", hr);
dev = device;
obj = first_obj;
while (obj) {
switch (obj->obj_type) {
case gs_type::gs_vertex_buffer:
((gs_vertex_buffer*)obj)->Rebuild();
break;
case gs_type::gs_index_buffer:
((gs_index_buffer*)obj)->Rebuild(dev);
break;
case gs_type::gs_texture_2d:
((gs_texture_2d*)obj)->Rebuild(dev);
break;
case gs_type::gs_zstencil_buffer:
((gs_zstencil_buffer*)obj)->Rebuild(dev);
break;
case gs_type::gs_stage_surface:
((gs_stage_surface*)obj)->Rebuild(dev);
break;
case gs_type::gs_sampler_state:
((gs_sampler_state*)obj)->Rebuild(dev);
break;
case gs_type::gs_vertex_shader:
((gs_vertex_shader*)obj)->Rebuild(dev);
break;
case gs_type::gs_pixel_shader:
((gs_pixel_shader*)obj)->Rebuild(dev);
break;
case gs_type::gs_duplicator:
((gs_duplicator*)obj)->Start();
break;
case gs_type::gs_swap_chain:
((gs_swap_chain*)obj)->Rebuild(dev);
break;
}
obj = obj->next;
}
curRenderTarget = nullptr;
curZStencilBuffer = nullptr;
curRenderSide = 0;
memset(&curTextures, 0, sizeof(curTextures));
memset(&curSamplers, 0, sizeof(curSamplers));
curVertexBuffer = nullptr;
curIndexBuffer = nullptr;
curVertexShader = nullptr;
curPixelShader = nullptr;
curSwapChain = nullptr;
zstencilStateChanged = true;
rasterStateChanged = true;
blendStateChanged = true;
curDepthStencilState = nullptr;
curRasterState = nullptr;
curBlendState = nullptr;
curToplogy = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
for (auto &state : zstencilStates)
state.Rebuild(dev);
for (auto &state : rasterStates)
state.Rebuild(dev);
for (auto &state : blendStates)
state.Rebuild(dev);
} catch (const char *error) {
bcrash("Failed to recreate D3D11: %s", error);
} catch (HRError error) {
bcrash("Failed to recreate D3D11: %s (%08lX)",
error.str, error.hr);
}

View file

@ -62,10 +62,9 @@ static inline D3D11_FILTER ConvertGSFilter( gs_sample_filter filter)
gs_sampler_state::gs_sampler_state(gs_device_t *device,
const gs_sampler_info *info)
: device (device),
: gs_obj (device, gs_type::gs_sampler_state),
info (*info)
{
D3D11_SAMPLER_DESC sd;
HRESULT hr;
vec4 v4;

View file

@ -40,13 +40,12 @@ void gs_vertex_shader::GetBuffersExpected(
gs_vertex_shader::gs_vertex_shader(gs_device_t *device, const char *file,
const char *shaderString)
: gs_shader (device, GS_SHADER_VERTEX),
: gs_shader (device, gs_type::gs_vertex_shader, GS_SHADER_VERTEX),
hasNormals (false),
hasColors (false),
hasTangents (false),
nTexUnits (0)
{
vector<D3D11_INPUT_ELEMENT_DESC> inputs;
ShaderProcessor processor(device);
ComPtr<ID3D10Blob> shaderBlob;
string outputString;
@ -55,20 +54,23 @@ gs_vertex_shader::gs_vertex_shader(gs_device_t *device, const char *file,
processor.Process(shaderString, file);
processor.BuildString(outputString);
processor.BuildParams(params);
processor.BuildInputLayout(inputs);
GetBuffersExpected(inputs);
processor.BuildInputLayout(layoutData);
GetBuffersExpected(layoutData);
BuildConstantBuffer();
Compile(outputString.c_str(), file, "vs_4_0", shaderBlob.Assign());
hr = device->device->CreateVertexShader(shaderBlob->GetBufferPointer(),
shaderBlob->GetBufferSize(), NULL, shader.Assign());
data.resize(shaderBlob->GetBufferSize());
memcpy(&data[0], shaderBlob->GetBufferPointer(), data.size());
hr = device->device->CreateVertexShader(data.data(), data.size(),
NULL, shader.Assign());
if (FAILED(hr))
throw HRError("Failed to create vertex shader", hr);
hr = device->device->CreateInputLayout(inputs.data(),
(UINT)inputs.size(), shaderBlob->GetBufferPointer(),
shaderBlob->GetBufferSize(), layout.Assign());
hr = device->device->CreateInputLayout(layoutData.data(),
(UINT)layoutData.size(),
data.data(), data.size(), layout.Assign());
if (FAILED(hr))
throw HRError("Failed to create input layout", hr);
@ -78,7 +80,7 @@ gs_vertex_shader::gs_vertex_shader(gs_device_t *device, const char *file,
gs_pixel_shader::gs_pixel_shader(gs_device_t *device, const char *file,
const char *shaderString)
: gs_shader(device, GS_SHADER_PIXEL)
: gs_shader(device, gs_type::gs_pixel_shader, GS_SHADER_PIXEL)
{
ShaderProcessor processor(device);
ComPtr<ID3D10Blob> shaderBlob;
@ -93,10 +95,13 @@ gs_pixel_shader::gs_pixel_shader(gs_device_t *device, const char *file,
Compile(outputString.c_str(), file, "ps_4_0", shaderBlob.Assign());
hr = device->device->CreatePixelShader(shaderBlob->GetBufferPointer(),
shaderBlob->GetBufferSize(), NULL, shader.Assign());
data.resize(shaderBlob->GetBufferSize());
memcpy(&data[0], shaderBlob->GetBufferPointer(), data.size());
hr = device->device->CreatePixelShader(data.data(), data.size(),
NULL, shader.Assign());
if (FAILED(hr))
throw HRError("Failed to create vertex shader", hr);
throw HRError("Failed to create pixel shader", hr);
}
/*
@ -157,11 +162,11 @@ void gs_shader::BuildConstantBuffer()
constantSize += size;
}
memset(&bd, 0, sizeof(bd));
if (constantSize) {
D3D11_BUFFER_DESC bd;
HRESULT hr;
memset(&bd, 0, sizeof(bd));
bd.ByteWidth = (constantSize+15)&0xFFFFFFF0; /* align */
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
@ -196,6 +201,22 @@ void gs_shader::Compile(const char *shaderString, const char *file,
else
throw HRError("Failed to compile shader", hr);
}
#ifdef DISASSEMBLE_SHADERS
ComPtr<ID3D10Blob> asmBlob;
if (!device->d3dDisassemble)
return;
hr = device->d3dDisassemble((*shader)->GetBufferPointer(),
(*shader)->GetBufferSize(), 0, nullptr, &asmBlob);
if (SUCCEEDED(hr) && !!asmBlob && asmBlob->GetBufferSize()) {
blog(LOG_INFO, "=============================================");
blog(LOG_INFO, "Disassembly output for shader '%s':\n%s",
file, asmBlob->GetBufferPointer());
}
#endif
}
inline void gs_shader::UpdateParam(vector<uint8_t> &constData,

View file

@ -181,14 +181,14 @@ void ShaderProcessor::BuildParams(vector<gs_shader_param> &params)
}
static inline void AddSampler(gs_device_t *device, shader_sampler &sampler,
vector<ShaderSampler> &samplers)
vector<unique_ptr<ShaderSampler>> &samplers)
{
gs_sampler_info si;
shader_sampler_convert(&sampler, &si);
samplers.push_back(ShaderSampler(sampler.name, device, &si));
samplers.emplace_back(new ShaderSampler(sampler.name, device, &si));
}
void ShaderProcessor::BuildSamplers(vector<ShaderSampler> &samplers)
void ShaderProcessor::BuildSamplers(vector<unique_ptr<ShaderSampler>> &samplers)
{
for (size_t i = 0; i < parser.samplers.num; i++)
AddSampler(device, parser.samplers.array[i], samplers);

View file

@ -30,7 +30,7 @@ struct ShaderProcessor {
void BuildInputLayout(vector<D3D11_INPUT_ELEMENT_DESC> &inputs);
void BuildParams(vector<gs_shader_param> &params);
void BuildSamplers(vector<ShaderSampler> &samplers);
void BuildSamplers(vector<unique_ptr<ShaderSampler>> &samplers);
void BuildString(string &outputString);
void Process(const char *shader_string, const char *file);

View file

@ -19,13 +19,12 @@
gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
uint32_t height, gs_color_format colorFormat)
: device (device),
: gs_obj (device, gs_type::gs_stage_surface),
width (width),
height (height),
format (colorFormat),
dxgiFormat (ConvertGSTextureFormat(colorFormat))
{
D3D11_TEXTURE2D_DESC td;
HRESULT hr;
memset(&td, 0, sizeof(td));
@ -40,5 +39,5 @@ gs_stage_surface::gs_stage_surface(gs_device_t *device, uint32_t width,
hr = device->device->CreateTexture2D(&td, NULL, texture.Assign());
if (FAILED(hr))
throw HRError("Failed to create 2D texture", hr);
throw HRError("Failed to create staging surface", hr);
}

View file

@ -33,9 +33,39 @@ struct UnsupportedHWError : HRError {
#pragma warning (disable : 4316)
#endif
static inline void LogD3D11ErrorDetails(HRError error, gs_device_t *device)
{
if (error.hr == DXGI_ERROR_DEVICE_REMOVED) {
HRESULT DeviceRemovedReason =
device->device->GetDeviceRemovedReason();
blog(LOG_ERROR, " Device Removed Reason: %08lX",
DeviceRemovedReason);
}
}
static const IID dxgiFactory2 =
{0x50c83a1c, 0xe072, 0x4c48, {0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0}};
gs_obj::gs_obj(gs_device_t *device_, gs_type type) :
device (device_),
obj_type (type)
{
prev_next = &device->first_obj;
next = device->first_obj;
device->first_obj = this;
if (next)
next->prev_next = &next;
}
gs_obj::~gs_obj()
{
if (prev_next)
*prev_next = next;
if (next)
next->prev_next = prev_next;
}
static inline void make_swap_desc(DXGI_SWAP_CHAIN_DESC &desc,
const gs_init_data *data)
{
@ -91,6 +121,9 @@ void gs_swap_chain::Resize(uint32_t cx, uint32_t cy)
zs.texture.Clear();
zs.view.Clear();
initData.cx = cx;
initData.cy = cy;
if (cx == 0 || cy == 0) {
GetClientRect(hwnd, &clientRect);
if (cx == 0) cx = clientRect.right;
@ -105,27 +138,27 @@ void gs_swap_chain::Resize(uint32_t cx, uint32_t cy)
InitZStencilBuffer(cx, cy);
}
void gs_swap_chain::Init(const gs_init_data *data)
void gs_swap_chain::Init()
{
target.device = device;
target.isRenderTarget = true;
target.format = data->format;
target.dxgiFormat = ConvertGSTextureFormat(data->format);
InitTarget(data->cx, data->cy);
target.format = initData.format;
target.dxgiFormat = ConvertGSTextureFormat(initData.format);
InitTarget(initData.cx, initData.cy);
zs.device = device;
zs.format = data->zsformat;
zs.dxgiFormat = ConvertGSZStencilFormat(data->zsformat);
InitZStencilBuffer(data->cx, data->cy);
zs.format = initData.zsformat;
zs.dxgiFormat = ConvertGSZStencilFormat(initData.zsformat);
InitZStencilBuffer(initData.cx, initData.cy);
}
gs_swap_chain::gs_swap_chain(gs_device *device, const gs_init_data *data)
: device (device),
: gs_obj (device, gs_type::gs_swap_chain),
numBuffers (data->num_backbuffers),
hwnd ((HWND)data->window.hwnd)
hwnd ((HWND)data->window.hwnd),
initData (*data)
{
HRESULT hr;
DXGI_SWAP_CHAIN_DESC swapDesc;
make_swap_desc(swapDesc, data);
hr = device->factory->CreateSwapChain(device->device, &swapDesc,
@ -133,7 +166,7 @@ gs_swap_chain::gs_swap_chain(gs_device *device, const gs_init_data *data)
if (FAILED(hr))
throw HRError("Failed to create swap chain", hr);
Init(data);
Init();
}
void gs_device::InitCompiler()
@ -148,6 +181,11 @@ void gs_device::InitCompiler()
if (module) {
d3dCompile = (pD3DCompile)GetProcAddress(module,
"D3DCompile");
#ifdef DISASSEMBLE_SHADERS
d3dDisassemble = (pD3DDisassemble)GetProcAddress(
module, "D3DDisassemble");
#endif
if (d3dCompile) {
return;
}
@ -161,7 +199,7 @@ void gs_device::InitCompiler()
throw "Could not find any D3DCompiler libraries";
}
void gs_device::InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **padapter)
void gs_device::InitFactory(uint32_t adapterIdx)
{
HRESULT hr;
IID factoryIID = (GetWinVer() >= 0x602) ? dxgiFactory2 :
@ -171,7 +209,7 @@ void gs_device::InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **padapter)
if (FAILED(hr))
throw UnsupportedHWError("Failed to create DXGIFactory", hr);
hr = factory->EnumAdapters1(adapterIdx, padapter);
hr = factory->EnumAdapters1(adapterIdx, &adapter);
if (FAILED(hr))
throw UnsupportedHWError("Failed to enumerate DXGIAdapter", hr);
}
@ -184,13 +222,15 @@ const static D3D_FEATURE_LEVEL featureLevels[] =
D3D_FEATURE_LEVEL_9_3,
};
void gs_device::InitDevice(uint32_t adapterIdx, IDXGIAdapter *adapter)
void gs_device::InitDevice(uint32_t adapterIdx)
{
wstring adapterName;
DXGI_ADAPTER_DESC desc;
D3D_FEATURE_LEVEL levelUsed = D3D_FEATURE_LEVEL_9_3;
HRESULT hr = 0;
adpIdx = adapterIdx;
uint32_t createFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef _DEBUG
//createFlags |= D3D11_CREATE_DEVICE_DEBUG;
@ -230,7 +270,6 @@ ID3D11DepthStencilState *gs_device::AddZStencilState()
{
HRESULT hr;
D3D11_DEPTH_STENCIL_DESC dsd;
SavedZStencilState savedState(zstencilState);
ID3D11DepthStencilState *state;
dsd.DepthEnable = zstencilState.depthEnabled;
@ -244,6 +283,7 @@ ID3D11DepthStencilState *gs_device::AddZStencilState()
ConvertStencilSide(dsd.FrontFace, zstencilState.stencilFront);
ConvertStencilSide(dsd.BackFace, zstencilState.stencilBack);
SavedZStencilState savedState(zstencilState, dsd);
hr = device->CreateDepthStencilState(&dsd, savedState.state.Assign());
if (FAILED(hr))
throw HRError("Failed to create depth stencil state", hr);
@ -258,7 +298,6 @@ ID3D11RasterizerState *gs_device::AddRasterState()
{
HRESULT hr;
D3D11_RASTERIZER_DESC rd;
SavedRasterState savedState(rasterState);
ID3D11RasterizerState *state;
memset(&rd, 0, sizeof(rd));
@ -269,6 +308,7 @@ ID3D11RasterizerState *gs_device::AddRasterState()
rd.DepthClipEnable = true;
rd.ScissorEnable = rasterState.scissorEnabled;
SavedRasterState savedState(rasterState, rd);
hr = device->CreateRasterizerState(&rd, savedState.state.Assign());
if (FAILED(hr))
throw HRError("Failed to create rasterizer state", hr);
@ -283,7 +323,6 @@ ID3D11BlendState *gs_device::AddBlendState()
{
HRESULT hr;
D3D11_BLEND_DESC bd;
SavedBlendState savedState(blendState);
ID3D11BlendState *state;
memset(&bd, 0, sizeof(bd));
@ -303,9 +342,10 @@ ID3D11BlendState *gs_device::AddBlendState()
D3D11_COLOR_WRITE_ENABLE_ALL;
}
SavedBlendState savedState(blendState, bd);
hr = device->CreateBlendState(&bd, savedState.state.Assign());
if (FAILED(hr))
throw HRError("Failed to create disabled blend state", hr);
throw HRError("Failed to create blend state", hr);
state = savedState.state;
blendStates.push_back(savedState);
@ -413,8 +453,6 @@ void gs_device::UpdateViewProjMatrix()
gs_device::gs_device(uint32_t adapterIdx)
: curToplogy (D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED)
{
ComPtr<IDXGIAdapter1> adapter;
matrix4_identity(&curProjMatrix);
matrix4_identity(&curViewMatrix);
matrix4_identity(&curViewProjMatrix);
@ -427,11 +465,16 @@ gs_device::gs_device(uint32_t adapterIdx)
}
InitCompiler();
InitFactory(adapterIdx, adapter.Assign());
InitDevice(adapterIdx, adapter);
InitFactory(adapterIdx);
InitDevice(adapterIdx);
device_set_render_target(this, NULL, NULL);
}
gs_device::~gs_device()
{
context->ClearState();
}
const char *device_get_name(void)
{
return "Direct3D 11";
@ -612,6 +655,7 @@ gs_swapchain_t *device_swapchain_create(gs_device_t *device,
} catch (HRError error) {
blog(LOG_ERROR, "device_swapchain_create (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return swap;
@ -641,6 +685,7 @@ void device_resize(gs_device_t *device, uint32_t cx, uint32_t cy)
} catch (HRError error) {
blog(LOG_ERROR, "device_resize (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
}
@ -688,6 +733,7 @@ gs_texture_t *device_texture_create(gs_device_t *device, uint32_t width,
} catch (HRError error) {
blog(LOG_ERROR, "device_texture_create (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (const char *error) {
blog(LOG_ERROR, "device_texture_create (D3D11): %s", error);
}
@ -708,6 +754,7 @@ gs_texture_t *device_cubetexture_create(gs_device_t *device, uint32_t size,
blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (const char *error) {
blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s",
error);
@ -743,6 +790,7 @@ gs_zstencil_t *device_zstencil_create(gs_device_t *device, uint32_t width,
} catch (HRError error) {
blog(LOG_ERROR, "device_zstencil_create (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return zstencil;
@ -759,6 +807,7 @@ gs_stagesurf_t *device_stagesurface_create(gs_device_t *device, uint32_t width,
blog(LOG_ERROR, "device_stagesurface_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return surf;
@ -774,6 +823,7 @@ gs_samplerstate_t *device_samplerstate_create(gs_device_t *device,
blog(LOG_ERROR, "device_samplerstate_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return ss;
@ -791,6 +841,7 @@ gs_shader_t *device_vertexshader_create(gs_device_t *device,
blog(LOG_ERROR, "device_vertexshader_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (ShaderError error) {
const char *buf = (const char*)error.errors->GetBufferPointer();
@ -820,6 +871,7 @@ gs_shader_t *device_pixelshader_create(gs_device_t *device,
blog(LOG_ERROR, "device_pixelshader_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (ShaderError error) {
const char *buf = (const char*)error.errors->GetBufferPointer();
@ -847,6 +899,7 @@ gs_vertbuffer_t *device_vertexbuffer_create(gs_device_t *device,
blog(LOG_ERROR, "device_vertexbuffer_create (D3D11): %s "
"(%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (const char *error) {
blog(LOG_ERROR, "device_vertexbuffer_create (D3D11): %s",
error);
@ -865,6 +918,7 @@ gs_indexbuffer_t *device_indexbuffer_create(gs_device_t *device,
} catch (HRError error) {
blog(LOG_ERROR, "device_indexbuffer_create (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
}
return buffer;
@ -1308,6 +1362,7 @@ void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
} catch (HRError error) {
blog(LOG_ERROR, "device_draw (D3D11): %s (%08lX)", error.str,
error.hr);
LogD3D11ErrorDetails(error, device);
return;
}
@ -1382,8 +1437,14 @@ void device_clear(gs_device_t *device, uint32_t clear_flags,
void device_present(gs_device_t *device)
{
HRESULT hr;
if (device->curSwapChain) {
device->curSwapChain->swap->Present(0, 0);
hr = device->curSwapChain->swap->Present(0, 0);
if (hr == DXGI_ERROR_DEVICE_REMOVED ||
hr == DXGI_ERROR_DEVICE_RESET) {
device->RebuildDevice();
}
} else {
blog(LOG_WARNING, "device_present (D3D11): No active swap");
}
@ -1964,6 +2025,7 @@ extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device,
} catch (HRError error) {
blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (const char *error) {
blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s", error);
}
@ -1993,6 +2055,9 @@ extern "C" EXPORT void *gs_texture_get_dc(gs_texture_t *tex)
if (!TextureGDICompatible(tex2d, "gs_texture_get_dc"))
return nullptr;
if (!tex2d->gdiSurface)
return nullptr;
tex2d->gdiSurface->GetDC(true, &hDC);
return hDC;
}
@ -2018,6 +2083,7 @@ extern "C" EXPORT gs_texture_t *device_texture_open_shared(gs_device_t *device,
} catch (HRError error) {
blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s (%08lX)",
error.str, error.hr);
LogD3D11ErrorDetails(error, device);
} catch (const char *error) {
blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s", error);
}

View file

@ -22,6 +22,7 @@
#include <vector>
#include <string>
#include <memory>
#include <windows.h>
#include <dxgi.h>
@ -36,6 +37,8 @@
#include <util/windows/ComPtr.hpp>
#include <util/windows/HRError.hpp>
// #define DISASSEMBLE_SHADERS
struct shader_var;
struct shader_sampler;
struct gs_vertex_shader;
@ -197,20 +200,46 @@ static inline D3D11_PRIMITIVE_TOPOLOGY ConvertGSTopology(gs_draw_mode mode)
struct VBDataPtr {
gs_vb_data *data;
inline void Clear() {gs_vbdata_destroy(data); data = nullptr;}
inline VBDataPtr(gs_vb_data *data) : data(data) {}
inline ~VBDataPtr() {gs_vbdata_destroy(data);}
};
struct gs_vertex_buffer {
enum class gs_type {
gs_vertex_buffer,
gs_index_buffer,
gs_texture_2d,
gs_zstencil_buffer,
gs_stage_surface,
gs_sampler_state,
gs_vertex_shader,
gs_pixel_shader,
gs_duplicator,
gs_swap_chain,
};
struct gs_obj {
gs_device_t *device;
gs_type obj_type;
gs_obj *next;
gs_obj **prev_next;
inline gs_obj() :
device(nullptr),
next(nullptr),
prev_next(nullptr)
{}
gs_obj(gs_device_t *device, gs_type type);
virtual ~gs_obj();
};
struct gs_vertex_buffer : gs_obj {
ComPtr<ID3D11Buffer> vertexBuffer;
ComPtr<ID3D11Buffer> normalBuffer;
ComPtr<ID3D11Buffer> colorBuffer;
ComPtr<ID3D11Buffer> tangentBuffer;
vector<ComPtr<ID3D11Buffer>> uvBuffers;
gs_device_t *device;
bool dynamic;
VBDataPtr vbd;
size_t numVerts;
@ -223,10 +252,23 @@ struct gs_vertex_buffer {
vector<ID3D11Buffer*> &buffers,
vector<uint32_t> &strides);
inline void InitBuffer(const size_t elementSize,
void InitBuffer(const size_t elementSize,
const size_t numVerts, void *array,
ID3D11Buffer **buffer);
void BuildBuffers();
inline void Release()
{
vertexBuffer.Release();
normalBuffer.Release();
colorBuffer.Release();
tangentBuffer.Release();
uvBuffers.clear();
}
inline void Rebuild();
gs_vertex_buffer(gs_device_t *device, struct gs_vb_data *data,
uint32_t flags);
};
@ -239,41 +281,61 @@ struct DataPtr {
inline ~DataPtr() {bfree(data);}
};
struct gs_index_buffer {
struct gs_index_buffer : gs_obj {
ComPtr<ID3D11Buffer> indexBuffer;
gs_device_t *device;
bool dynamic;
gs_index_type type;
size_t indexSize;
size_t num;
DataPtr indices;
D3D11_BUFFER_DESC bd = {};
D3D11_SUBRESOURCE_DATA srd = {};
void InitBuffer();
inline void Rebuild(ID3D11Device *dev);
inline void Release() {indexBuffer.Release();}
gs_index_buffer(gs_device_t *device, enum gs_index_type type,
void *indices, size_t num, uint32_t flags);
};
struct gs_texture {
struct gs_texture : gs_obj {
gs_texture_type type;
gs_device *device;
uint32_t levels;
gs_color_format format;
ComPtr<ID3D11ShaderResourceView> shaderRes;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc = {};
inline gs_texture() {}
inline void Rebuild(ID3D11Device *dev);
inline gs_texture(gs_device *device, gs_texture_type type,
uint32_t levels, gs_color_format format)
inline gs_texture(gs_texture_type type, uint32_t levels,
gs_color_format format)
: type (type),
device (device),
levels (levels),
format (format)
{
}
virtual ~gs_texture() {}
inline gs_texture(gs_device *device, gs_type obj_type,
gs_texture_type type)
: gs_obj (device, obj_type),
type (type)
{
}
inline gs_texture(gs_device *device, gs_type obj_type,
gs_texture_type type,
uint32_t levels, gs_color_format format)
: gs_obj (device, obj_type),
type (type),
levels (levels),
format (format)
{
}
};
struct gs_texture_2d : gs_texture {
@ -290,13 +352,30 @@ struct gs_texture_2d : gs_texture {
bool genMipmaps = false;
uint32_t sharedHandle = 0;
void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd, const uint8_t **data);
vector<vector<uint8_t>> data;
vector<D3D11_SUBRESOURCE_DATA> srd;
D3D11_TEXTURE2D_DESC td = {};
void InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd);
void InitTexture(const uint8_t **data);
void InitResourceView();
void InitRenderTargets();
void BackupTexture(const uint8_t **data);
void RebuildSharedTextureFallback();
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
texture.Release();
for (auto &rt : renderTarget)
rt.Release();
gdiSurface.Release();
shaderRes.Release();
}
inline gs_texture_2d()
: gs_texture (NULL, GS_TEXTURE_2D, 0, GS_UNKNOWN)
: gs_texture (GS_TEXTURE_2D, 0, GS_UNKNOWN)
{
}
@ -308,20 +387,29 @@ struct gs_texture_2d : gs_texture {
gs_texture_2d(gs_device_t *device, uint32_t handle);
};
struct gs_zstencil_buffer {
struct gs_zstencil_buffer : gs_obj {
ComPtr<ID3D11Texture2D> texture;
ComPtr<ID3D11DepthStencilView> view;
gs_device *device;
uint32_t width, height;
gs_zstencil_format format;
DXGI_FORMAT dxgiFormat;
D3D11_TEXTURE2D_DESC td = {};
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd = {};
void InitBuffer();
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
texture.Release();
view.Release();
}
inline gs_zstencil_buffer()
: device (NULL),
width (0),
: width (0),
height (0),
dxgiFormat (DXGI_FORMAT_UNKNOWN)
{
@ -331,23 +419,34 @@ struct gs_zstencil_buffer {
gs_zstencil_format format);
};
struct gs_stage_surface {
struct gs_stage_surface : gs_obj {
ComPtr<ID3D11Texture2D> texture;
D3D11_TEXTURE2D_DESC td = {};
gs_device *device;
uint32_t width, height;
gs_color_format format;
DXGI_FORMAT dxgiFormat;
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
texture.Release();
}
gs_stage_surface(gs_device_t *device, uint32_t width, uint32_t height,
gs_color_format colorFormat);
};
struct gs_sampler_state {
struct gs_sampler_state : gs_obj {
ComPtr<ID3D11SamplerState> state;
gs_device_t *device;
D3D11_SAMPLER_DESC sd = {};
gs_sampler_info info;
inline void Rebuild(ID3D11Device *dev);
inline void Release() {state.Release();}
gs_sampler_state(gs_device_t *device, const gs_sampler_info *info);
};
@ -380,13 +479,15 @@ struct ShaderError {
}
};
struct gs_shader {
gs_device_t *device;
struct gs_shader : gs_obj {
gs_shader_type type;
vector<gs_shader_param> params;
ComPtr<ID3D11Buffer> constants;
size_t constantSize;
D3D11_BUFFER_DESC bd = {};
vector<uint8_t> data;
inline void UpdateParam(vector<uint8_t> &constData,
gs_shader_param &param, bool &upload);
void UploadParams();
@ -395,8 +496,9 @@ struct gs_shader {
void Compile(const char *shaderStr, const char *file,
const char *target, ID3D10Blob **shader);
inline gs_shader(gs_device_t *device, gs_shader_type type)
: device (device),
inline gs_shader(gs_device_t *device, gs_type obj_type,
gs_shader_type type)
: gs_obj (device, obj_type),
type (type),
constantSize (0)
{
@ -423,11 +525,22 @@ struct gs_vertex_shader : gs_shader {
gs_shader_param *world, *viewProj;
vector<D3D11_INPUT_ELEMENT_DESC> layoutData;
bool hasNormals;
bool hasColors;
bool hasTangents;
uint32_t nTexUnits;
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
shader.Release();
layout.Release();
constants.Release();
}
inline uint32_t NumBuffersExpected() const
{
uint32_t count = nTexUnits+1;
@ -444,10 +557,17 @@ struct gs_vertex_shader : gs_shader {
const char *shaderString);
};
struct gs_duplicator {
struct gs_duplicator : gs_obj {
ComPtr<IDXGIOutputDuplication> duplicator;
gs_texture_2d *texture;
gs_device_t *device;
int idx;
void Start();
inline void Release()
{
duplicator.Release();
}
gs_duplicator(gs_device_t *device, int monitor_idx);
~gs_duplicator();
@ -455,13 +575,21 @@ struct gs_duplicator {
struct gs_pixel_shader : gs_shader {
ComPtr<ID3D11PixelShader> shader;
vector<ShaderSampler> samplers;
vector<unique_ptr<ShaderSampler>> samplers;
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
shader.Release();
constants.Release();
}
inline void GetSamplerStates(ID3D11SamplerState **states)
{
size_t i;
for (i = 0; i < samplers.size(); i++)
states[i] = samplers[i].sampler.state;
states[i] = samplers[i]->sampler.state;
for (; i < GS_MAX_TEXTURES; i++)
states[i] = NULL;
}
@ -470,10 +598,11 @@ struct gs_pixel_shader : gs_shader {
const char *shaderString);
};
struct gs_swap_chain {
gs_device *device;
struct gs_swap_chain : gs_obj {
uint32_t numBuffers;
HWND hwnd;
gs_init_data initData;
DXGI_SWAP_CHAIN_DESC swapDesc = {};
gs_texture_2d target;
gs_zstencil_buffer zs;
@ -482,13 +611,15 @@ struct gs_swap_chain {
void InitTarget(uint32_t cx, uint32_t cy);
void InitZStencilBuffer(uint32_t cx, uint32_t cy);
void Resize(uint32_t cx, uint32_t cy);
void Init(const gs_init_data *data);
void Init();
inline gs_swap_chain()
: device (NULL),
numBuffers (0),
hwnd (NULL)
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
target.Release();
zs.Release();
swap.Release();
}
gs_swap_chain(gs_device *device, const gs_init_data *data);
@ -527,8 +658,17 @@ struct BlendState {
struct SavedBlendState : BlendState {
ComPtr<ID3D11BlendState> state;
D3D11_BLEND_DESC bd;
inline SavedBlendState(const BlendState &val) : BlendState(val)
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
state.Release();
}
inline SavedBlendState(const BlendState &val, D3D11_BLEND_DESC &desc)
: BlendState(val), bd(desc)
{
}
};
@ -575,9 +715,19 @@ struct ZStencilState {
struct SavedZStencilState : ZStencilState {
ComPtr<ID3D11DepthStencilState> state;
D3D11_DEPTH_STENCIL_DESC dsd;
inline SavedZStencilState(const ZStencilState &val)
: ZStencilState (val)
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
state.Release();
}
inline SavedZStencilState(const ZStencilState &val,
D3D11_DEPTH_STENCIL_DESC desc)
: ZStencilState (val),
dsd (desc)
{
}
};
@ -600,9 +750,19 @@ struct RasterState {
struct SavedRasterState : RasterState {
ComPtr<ID3D11RasterizerState> state;
D3D11_RASTERIZER_DESC rd;
inline SavedRasterState(const RasterState &val)
: RasterState (val)
inline void Rebuild(ID3D11Device *dev);
inline void Release()
{
state.Release();
}
inline SavedRasterState(const RasterState &val,
D3D11_RASTERIZER_DESC &desc)
: RasterState (val),
rd (desc)
{
}
};
@ -613,8 +773,10 @@ struct mat4float {
struct gs_device {
ComPtr<IDXGIFactory1> factory;
ComPtr<IDXGIAdapter1> adapter;
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
uint32_t adpIdx = 0;
gs_texture_2d *curRenderTarget = nullptr;
gs_zstencil_buffer *curZStencilBuffer = nullptr;
@ -642,6 +804,9 @@ struct gs_device {
D3D11_PRIMITIVE_TOPOLOGY curToplogy;
pD3DCompile d3dCompile = nullptr;
#ifdef DISASSEMBLE_SHADERS
pD3DDisassemble d3dDisassemble = nullptr;
#endif
gs_rect viewport;
@ -651,9 +816,11 @@ struct gs_device {
matrix4 curViewMatrix;
matrix4 curViewProjMatrix;
gs_obj *first_obj = nullptr;
void InitCompiler();
void InitFactory(uint32_t adapterIdx, IDXGIAdapter1 **adapter);
void InitDevice(uint32_t adapterIdx, IDXGIAdapter *adapter);
void InitFactory(uint32_t adapterIdx);
void InitDevice(uint32_t adapterIdx);
ID3D11DepthStencilState *AddZStencilState();
ID3D11RasterizerState *AddRasterState();
@ -669,5 +836,8 @@ struct gs_device {
void UpdateViewProjMatrix();
void RebuildDevice();
gs_device(uint32_t adapterIdx);
~gs_device();
};

View file

@ -18,13 +18,13 @@
#include <util/base.h>
#include "d3d11-subsystem.hpp"
void gs_texture_2d::InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd,
const uint8_t **data)
void gs_texture_2d::InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd)
{
uint32_t rowSizeBytes = width * gs_get_format_bpp(format);
uint32_t texSizeBytes = height * rowSizeBytes / 8;
size_t textures = type == GS_TEXTURE_2D ? 1 : 6;
uint32_t actual_levels = levels;
size_t curTex = 0;
if (!actual_levels)
actual_levels = gs_get_total_levels(width, height);
@ -37,22 +37,42 @@ void gs_texture_2d::InitSRD(vector<D3D11_SUBRESOURCE_DATA> &srd,
for (uint32_t j = 0; j < actual_levels; j++) {
D3D11_SUBRESOURCE_DATA newSRD;
newSRD.pSysMem = *data;
newSRD.pSysMem = data[curTex++].data();
newSRD.SysMemPitch = newRowSize;
newSRD.SysMemSlicePitch = newTexSize;
srd.push_back(newSRD);
newRowSize /= 2;
newTexSize /= 4;
data++;
}
}
}
void gs_texture_2d::BackupTexture(const uint8_t **data)
{
this->data.resize(levels);
uint32_t w = width;
uint32_t h = height;
uint32_t bbp = gs_get_format_bpp(format);
for (uint32_t i = 0; i < levels; i++) {
if (!data[i])
break;
uint32_t texSize = bbp * w * h / 8;
this->data[i].resize(texSize);
vector<uint8_t> &subData = this->data[i];
memcpy(&subData[0], data[i], texSize);
w /= 2;
h /= 2;
}
}
void gs_texture_2d::InitTexture(const uint8_t **data)
{
vector<D3D11_SUBRESOURCE_DATA> srd;
D3D11_TEXTURE2D_DESC td;
HRESULT hr;
memset(&td, 0, sizeof(td));
@ -76,8 +96,10 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
if (isGDICompatible)
td.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
if (data)
InitSRD(srd, data);
if (data) {
BackupTexture(data);
InitSRD(srd);
}
hr = device->device->CreateTexture2D(&td, data ? srd.data() : NULL,
texture.Assign());
@ -94,7 +116,6 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
void gs_texture_2d::InitResourceView()
{
D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc;
HRESULT hr;
memset(&resourceDesc, 0, sizeof(resourceDesc));
@ -145,7 +166,8 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
uint32_t height, gs_color_format colorFormat, uint32_t levels,
const uint8_t **data, uint32_t flags, gs_texture_type type,
bool gdiCompatible, bool shared)
: gs_texture (device, type, levels, colorFormat),
: gs_texture (device, gs_type::gs_texture_2d, type, levels,
colorFormat),
width (width),
height (height),
dxgiFormat (ConvertGSTextureFormat(format)),
@ -163,29 +185,30 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
}
gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t handle)
: isShared (true),
: gs_texture (device, gs_type::gs_texture_2d,
GS_TEXTURE_2D),
isShared (true),
sharedHandle (handle)
{
HRESULT hr;
hr = device->device->OpenSharedResource((HANDLE)(uintptr_t)handle,
__uuidof(ID3D11Texture2D), (void**)texture.Assign());
if (FAILED(hr))
throw HRError("Failed to open resource", hr);
throw HRError("Failed to open shared 2D texture", hr);
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
texture->GetDesc(&td);
this->type = GS_TEXTURE_2D;
this->format = ConvertDXGITextureFormat(desc.Format);
this->format = ConvertDXGITextureFormat(td.Format);
this->levels = 1;
this->device = device;
this->width = desc.Width;
this->height = desc.Height;
this->dxgiFormat = desc.Format;
this->width = td.Width;
this->height = td.Height;
this->dxgiFormat = td.Format;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc = {};
resourceDesc.Format = desc.Format;
memset(&resourceDesc, 0, sizeof(resourceDesc));
resourceDesc.Format = td.Format;
resourceDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceDesc.Texture2D.MipLevels = 1;

View file

@ -72,7 +72,7 @@ void gs_vertex_buffer::MakeBufferList(gs_vertex_shader *shader,
}
}
inline void gs_vertex_buffer::InitBuffer(const size_t elementSize,
void gs_vertex_buffer::InitBuffer(const size_t elementSize,
const size_t numVerts, void *array, ID3D11Buffer **buffer)
{
D3D11_BUFFER_DESC bd;
@ -93,9 +93,43 @@ inline void gs_vertex_buffer::InitBuffer(const size_t elementSize,
throw HRError("Failed to create buffer", hr);
}
void gs_vertex_buffer::BuildBuffers()
{
InitBuffer(sizeof(vec3), vbd.data->num, vbd.data->points,
&vertexBuffer);
if (vbd.data->normals)
InitBuffer(sizeof(vec3), vbd.data->num, vbd.data->normals,
&normalBuffer);
if (vbd.data->tangents)
InitBuffer(sizeof(vec3), vbd.data->num, vbd.data->tangents,
&tangentBuffer);
if (vbd.data->colors)
InitBuffer(sizeof(uint32_t), vbd.data->num, vbd.data->colors,
&colorBuffer);
for (size_t i = 0; i < vbd.data->num_tex; i++) {
struct gs_tvertarray *tverts = vbd.data->tvarray+i;
if (tverts->width != 2 && tverts->width != 4)
throw "Invalid texture vertex size specified";
if (!tverts->array)
throw "No texture vertices specified";
ComPtr<ID3D11Buffer> buffer;
InitBuffer(tverts->width * sizeof(float), vbd.data->num,
tverts->array, &buffer);
uvBuffers.push_back(buffer);
uvSizes.push_back(tverts->width * sizeof(float));
}
}
gs_vertex_buffer::gs_vertex_buffer(gs_device_t *device, struct gs_vb_data *data,
uint32_t flags)
: device (device),
: gs_obj (device, gs_type::gs_vertex_buffer),
dynamic ((flags & GS_DYNAMIC) != 0),
vbd (data),
numVerts (data->num)
@ -105,37 +139,5 @@ gs_vertex_buffer::gs_vertex_buffer(gs_device_t *device, struct gs_vb_data *data,
if (!data->points)
throw "No points specified for vertex buffer";
InitBuffer(sizeof(vec3), data->num, data->points,
vertexBuffer.Assign());
if (data->normals)
InitBuffer(sizeof(vec3), data->num, data->normals,
normalBuffer.Assign());
if (data->tangents)
InitBuffer(sizeof(vec3), data->num, data->tangents,
tangentBuffer.Assign());
if (data->colors)
InitBuffer(sizeof(uint32_t), data->num, data->colors,
colorBuffer.Assign());
for (size_t i = 0; i < data->num_tex; i++) {
struct gs_tvertarray *tverts = data->tvarray+i;
if (tverts->width != 2 && tverts->width != 4)
throw "Invalid texture vertex size specified";
if (!tverts->array)
throw "No texture vertices specified";
ComPtr<ID3D11Buffer> buffer;
InitBuffer(tverts->width * sizeof(float), data->num,
tverts->array, buffer.Assign());
uvBuffers.push_back(buffer);
uvSizes.push_back(tverts->width * sizeof(float));
}
if (!dynamic)
vbd.Clear();
BuildBuffers();
}

View file

@ -19,8 +19,6 @@
void gs_zstencil_buffer::InitBuffer()
{
D3D11_TEXTURE2D_DESC td;
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
HRESULT hr;
memset(&td, 0, sizeof(td));
@ -50,7 +48,7 @@ void gs_zstencil_buffer::InitBuffer()
gs_zstencil_buffer::gs_zstencil_buffer(gs_device_t *device,
uint32_t width, uint32_t height,
gs_zstencil_format format)
: device (device),
: gs_obj (device, gs_type::gs_zstencil_buffer),
width (width),
height (height),
format (format),