mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-21 20:52:12 +01:00
81229d66cc
Fixes linker errors when building against winelib.
436 lines
14 KiB
C++
436 lines
14 KiB
C++
#include "d3d10_state_block.h"
|
|
|
|
#define MAKE_STATE_TYPE(field, count) { offsetof(D3D10_STATE_BLOCK_MASK, field), count }
|
|
|
|
namespace dxvk {
|
|
|
|
static const std::array<std::pair<size_t, size_t>, 24> g_stateTypes = {{
|
|
MAKE_STATE_TYPE(SOBuffers, 1),
|
|
MAKE_STATE_TYPE(OMRenderTargets, 1),
|
|
MAKE_STATE_TYPE(OMDepthStencilState, 1),
|
|
MAKE_STATE_TYPE(OMBlendState, 1),
|
|
MAKE_STATE_TYPE(VS, 1),
|
|
MAKE_STATE_TYPE(VSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(VSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(VSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(GS, 1),
|
|
MAKE_STATE_TYPE(GSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(GSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(GSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(PS, 1),
|
|
MAKE_STATE_TYPE(PSSamplers, D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(PSShaderResources, D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(PSConstantBuffers, D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(IAVertexBuffers, D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT),
|
|
MAKE_STATE_TYPE(IAIndexBuffer, 1),
|
|
MAKE_STATE_TYPE(IAInputLayout, 1),
|
|
MAKE_STATE_TYPE(IAPrimitiveTopology, 1),
|
|
MAKE_STATE_TYPE(RSViewports, 1),
|
|
MAKE_STATE_TYPE(RSScissorRects, 1),
|
|
MAKE_STATE_TYPE(RSRasterizerState, 1),
|
|
MAKE_STATE_TYPE(Predication, 1),
|
|
}};
|
|
|
|
// MinGW fails on __uuidof(ID3D10StateBlock), winelib builds fail to link
|
|
const GUID D3D10StateBlock::guid = {0x0803425a,0x57f5,0x4dd6,{0x94,0x65,0xa8,0x75,0x70,0x83,0x4a,0x08}};
|
|
|
|
|
|
D3D10StateBlock::D3D10StateBlock(
|
|
ID3D10Device* pDevice,
|
|
const D3D10_STATE_BLOCK_MASK* pMask)
|
|
: m_device(pDevice), m_mask(*pMask) {
|
|
|
|
}
|
|
|
|
|
|
D3D10StateBlock::~D3D10StateBlock() {
|
|
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlock::QueryInterface(
|
|
REFIID riid,
|
|
void** ppvObject) {
|
|
if (ppvObject == nullptr)
|
|
return E_POINTER;
|
|
|
|
*ppvObject = nullptr;
|
|
|
|
if (riid == __uuidof(IUnknown)
|
|
|| riid == D3D10StateBlock::guid) {
|
|
*ppvObject = ref(this);
|
|
return S_OK;
|
|
}
|
|
|
|
Logger::warn("D3D10StateBlock::QueryInterface: Unknown interface query");
|
|
Logger::warn(str::format(riid));
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlock::Capture() {
|
|
m_state = D3D10_STATE_BLOCK_STATE();
|
|
|
|
if (TestBit(&m_mask.VS, 0)) m_device->VSGetShader(&m_state.vs);
|
|
if (TestBit(&m_mask.GS, 0)) m_device->GSGetShader(&m_state.gs);
|
|
if (TestBit(&m_mask.PS, 0)) m_device->PSGetShader(&m_state.ps);
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSSamplers, i)) m_device->VSGetSamplers(i, 1, &m_state.vsSso[i]);
|
|
if (TestBit(m_mask.GSSamplers, i)) m_device->GSGetSamplers(i, 1, &m_state.gsSso[i]);
|
|
if (TestBit(m_mask.PSSamplers, i)) m_device->PSGetSamplers(i, 1, &m_state.psSso[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSShaderResources, i)) m_device->VSGetShaderResources(i, 1, &m_state.vsSrv[i]);
|
|
if (TestBit(m_mask.GSShaderResources, i)) m_device->GSGetShaderResources(i, 1, &m_state.gsSrv[i]);
|
|
if (TestBit(m_mask.PSShaderResources, i)) m_device->PSGetShaderResources(i, 1, &m_state.psSrv[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSConstantBuffers, i)) m_device->VSGetConstantBuffers(i, 1, &m_state.vsCbo[i]);
|
|
if (TestBit(m_mask.GSConstantBuffers, i)) m_device->GSGetConstantBuffers(i, 1, &m_state.gsCbo[i]);
|
|
if (TestBit(m_mask.PSConstantBuffers, i)) m_device->PSGetConstantBuffers(i, 1, &m_state.psCbo[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.IAVertexBuffers, i)) {
|
|
m_device->IAGetVertexBuffers(i, 1,
|
|
&m_state.iaVertexBuffers[i],
|
|
&m_state.iaVertexOffsets[i],
|
|
&m_state.iaVertexStrides[i]);
|
|
}
|
|
}
|
|
|
|
if (TestBit(&m_mask.IAIndexBuffer, 0)) {
|
|
m_device->IAGetIndexBuffer(
|
|
&m_state.iaIndexBuffer,
|
|
&m_state.iaIndexFormat,
|
|
&m_state.iaIndexOffset);
|
|
}
|
|
|
|
if (TestBit(&m_mask.IAInputLayout, 0))
|
|
m_device->IAGetInputLayout(&m_state.iaInputLayout);
|
|
|
|
if (TestBit(&m_mask.IAPrimitiveTopology, 0))
|
|
m_device->IAGetPrimitiveTopology(&m_state.iaTopology);
|
|
|
|
if (TestBit(&m_mask.OMRenderTargets, 0)) {
|
|
m_device->OMGetRenderTargets(
|
|
D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT,
|
|
&m_state.omRtv[0], &m_state.omDsv);
|
|
}
|
|
|
|
if (TestBit(&m_mask.OMDepthStencilState, 0)) {
|
|
m_device->OMGetDepthStencilState(
|
|
&m_state.omDepthStencilState,
|
|
&m_state.omStencilRef);
|
|
}
|
|
|
|
if (TestBit(&m_mask.OMBlendState, 0)) {
|
|
m_device->OMGetBlendState(
|
|
&m_state.omBlendState,
|
|
m_state.omBlendFactor,
|
|
&m_state.omSampleMask);
|
|
}
|
|
|
|
if (TestBit(&m_mask.RSViewports, 0)) {
|
|
m_device->RSGetViewports(&m_state.rsViewportCount, nullptr);
|
|
m_device->RSGetViewports(&m_state.rsViewportCount, m_state.rsViewports);
|
|
}
|
|
|
|
if (TestBit(&m_mask.RSScissorRects, 0)) {
|
|
m_device->RSGetScissorRects(&m_state.rsScissorCount, nullptr);
|
|
m_device->RSGetScissorRects(&m_state.rsScissorCount, m_state.rsScissors);
|
|
}
|
|
|
|
if (TestBit(&m_mask.RSRasterizerState, 0))
|
|
m_device->RSGetState(&m_state.rsState);
|
|
|
|
if (TestBit(&m_mask.SOBuffers, 0)) {
|
|
m_device->SOGetTargets(
|
|
D3D10_SO_BUFFER_SLOT_COUNT,
|
|
&m_state.soBuffers[0],
|
|
&m_state.soOffsets[0]);
|
|
}
|
|
|
|
if (TestBit(&m_mask.Predication, 0))
|
|
m_device->GetPredication(&m_state.predicate, &m_state.predicateInvert);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlock::Apply() {
|
|
if (TestBit(&m_mask.VS, 0)) m_device->VSSetShader(m_state.vs.ptr());
|
|
if (TestBit(&m_mask.GS, 0)) m_device->GSSetShader(m_state.gs.ptr());
|
|
if (TestBit(&m_mask.PS, 0)) m_device->PSSetShader(m_state.ps.ptr());
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSSamplers, i)) m_device->VSSetSamplers(i, 1, &m_state.vsSso[i]);
|
|
if (TestBit(m_mask.GSSamplers, i)) m_device->GSSetSamplers(i, 1, &m_state.gsSso[i]);
|
|
if (TestBit(m_mask.PSSamplers, i)) m_device->PSSetSamplers(i, 1, &m_state.psSso[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSShaderResources, i)) m_device->VSSetShaderResources(i, 1, &m_state.vsSrv[i]);
|
|
if (TestBit(m_mask.GSShaderResources, i)) m_device->GSSetShaderResources(i, 1, &m_state.gsSrv[i]);
|
|
if (TestBit(m_mask.PSShaderResources, i)) m_device->PSSetShaderResources(i, 1, &m_state.psSrv[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.VSConstantBuffers, i)) m_device->VSSetConstantBuffers(i, 1, &m_state.vsCbo[i]);
|
|
if (TestBit(m_mask.GSConstantBuffers, i)) m_device->GSSetConstantBuffers(i, 1, &m_state.gsCbo[i]);
|
|
if (TestBit(m_mask.PSConstantBuffers, i)) m_device->PSSetConstantBuffers(i, 1, &m_state.psCbo[i]);
|
|
}
|
|
|
|
for (uint32_t i = 0; i < D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++) {
|
|
if (TestBit(m_mask.IAVertexBuffers, i)) {
|
|
m_device->IASetVertexBuffers(i, 1,
|
|
&m_state.iaVertexBuffers[i],
|
|
&m_state.iaVertexOffsets[i],
|
|
&m_state.iaVertexStrides[i]);
|
|
}
|
|
}
|
|
|
|
if (TestBit(&m_mask.IAIndexBuffer, 0)) {
|
|
m_device->IASetIndexBuffer(
|
|
m_state.iaIndexBuffer.ptr(),
|
|
m_state.iaIndexFormat,
|
|
m_state.iaIndexOffset);
|
|
}
|
|
|
|
if (TestBit(&m_mask.IAInputLayout, 0))
|
|
m_device->IASetInputLayout(m_state.iaInputLayout.ptr());
|
|
|
|
if (TestBit(&m_mask.IAPrimitiveTopology, 0))
|
|
m_device->IASetPrimitiveTopology(m_state.iaTopology);
|
|
|
|
if (TestBit(&m_mask.OMRenderTargets, 0)) {
|
|
m_device->OMSetRenderTargets(
|
|
D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT,
|
|
&m_state.omRtv[0], m_state.omDsv.ptr());
|
|
}
|
|
|
|
if (TestBit(&m_mask.OMDepthStencilState, 0)) {
|
|
m_device->OMSetDepthStencilState(
|
|
m_state.omDepthStencilState.ptr(),
|
|
m_state.omStencilRef);
|
|
}
|
|
|
|
if (TestBit(&m_mask.OMBlendState, 0)) {
|
|
m_device->OMSetBlendState(
|
|
m_state.omBlendState.ptr(),
|
|
m_state.omBlendFactor,
|
|
m_state.omSampleMask);
|
|
}
|
|
|
|
if (TestBit(&m_mask.RSViewports, 0))
|
|
m_device->RSSetViewports(m_state.rsViewportCount, m_state.rsViewports);
|
|
|
|
if (TestBit(&m_mask.RSScissorRects, 0))
|
|
m_device->RSSetScissorRects(m_state.rsScissorCount, m_state.rsScissors);
|
|
|
|
if (TestBit(&m_mask.RSRasterizerState, 0))
|
|
m_device->RSSetState(m_state.rsState.ptr());
|
|
|
|
if (TestBit(&m_mask.SOBuffers, 0)) {
|
|
m_device->SOSetTargets(
|
|
D3D10_SO_BUFFER_SLOT_COUNT,
|
|
&m_state.soBuffers[0],
|
|
&m_state.soOffsets[0]);
|
|
}
|
|
|
|
if (TestBit(&m_mask.Predication, 0))
|
|
m_device->SetPredication(m_state.predicate.ptr(), m_state.predicateInvert);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlock::GetDevice(
|
|
ID3D10Device** ppDevice) {
|
|
Logger::err("D3D10StateBlock::GetDevice: Stub");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlock::ReleaseAllDeviceObjects() {
|
|
// Not entirely sure if this is correct?
|
|
m_state = D3D10_STATE_BLOCK_STATE();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
BOOL D3D10StateBlock::TestBit(
|
|
const BYTE* pMask,
|
|
UINT Idx) {
|
|
uint32_t byte = Idx / 8;
|
|
uint32_t bit = Idx % 8;
|
|
return (pMask[byte] & (1 << bit)) != 0;
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
using namespace dxvk;
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10CreateStateBlock(
|
|
ID3D10Device* pDevice,
|
|
D3D10_STATE_BLOCK_MASK* pStateBlockMask,
|
|
ID3D10StateBlock** ppStateBlock) {
|
|
InitReturnPtr(ppStateBlock);
|
|
|
|
if (!pDevice || !pStateBlockMask || !ppStateBlock)
|
|
return E_INVALIDARG;
|
|
|
|
*ppStateBlock = ref(new D3D10StateBlock(pDevice, pStateBlockMask));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskEnableCapture(
|
|
D3D10_STATE_BLOCK_MASK* pMask,
|
|
D3D10_DEVICE_STATE_TYPES StateType,
|
|
UINT StartIdx,
|
|
UINT Count) {
|
|
if (!pMask || !StateType || StateType > g_stateTypes.size())
|
|
return E_INVALIDARG;
|
|
|
|
auto pair = g_stateTypes[uint32_t(StateType) - 1];
|
|
auto mask = reinterpret_cast<BYTE*>(pMask) + pair.first;
|
|
|
|
if (StartIdx + Count > pair.second)
|
|
return E_INVALIDARG;
|
|
|
|
for (uint32_t i = StartIdx; i < StartIdx + Count; i++) {
|
|
uint32_t byte = i / 8;
|
|
uint32_t bit = i % 8;
|
|
mask[byte] |= 1 << bit;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDisableCapture(
|
|
D3D10_STATE_BLOCK_MASK* pMask,
|
|
D3D10_DEVICE_STATE_TYPES StateType,
|
|
UINT StartIdx,
|
|
UINT Count) {
|
|
if (!pMask || !StateType || StateType > g_stateTypes.size())
|
|
return E_INVALIDARG;
|
|
|
|
auto pair = g_stateTypes[uint32_t(StateType) - 1];
|
|
auto mask = reinterpret_cast<BYTE*>(pMask) + pair.first;
|
|
|
|
if (StartIdx + Count > pair.second)
|
|
return E_INVALIDARG;
|
|
|
|
for (uint32_t i = StartIdx; i < StartIdx + Count; i++) {
|
|
uint32_t byte = i / 8;
|
|
uint32_t bit = i % 8;
|
|
mask[byte] &= ~(1 << bit);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskEnableAll(
|
|
D3D10_STATE_BLOCK_MASK* pMask) {
|
|
if (!pMask)
|
|
return E_INVALIDARG;
|
|
|
|
*pMask = D3D10_STATE_BLOCK_MASK();
|
|
for (size_t i = 0; i < g_stateTypes.size(); i++) {
|
|
D3D10StateBlockMaskEnableCapture(pMask,
|
|
D3D10_DEVICE_STATE_TYPES(i + 1),
|
|
0, g_stateTypes[i].second);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDisableAll(
|
|
D3D10_STATE_BLOCK_MASK* pMask) {
|
|
if (!pMask)
|
|
return E_INVALIDARG;
|
|
|
|
*pMask = D3D10_STATE_BLOCK_MASK();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
BOOL STDMETHODCALLTYPE D3D10StateBlockMaskGetSetting(
|
|
D3D10_STATE_BLOCK_MASK* pMask,
|
|
D3D10_DEVICE_STATE_TYPES StateType,
|
|
UINT Idx) {
|
|
if (!pMask || !StateType || StateType > g_stateTypes.size())
|
|
return FALSE;
|
|
|
|
auto pair = g_stateTypes[uint32_t(StateType) - 1];
|
|
auto mask = reinterpret_cast<BYTE*>(pMask) + pair.first;
|
|
|
|
if (Idx >= pair.second)
|
|
return FALSE;
|
|
|
|
uint32_t byte = Idx / 8;
|
|
uint32_t bit = Idx % 8;
|
|
return (mask[byte] & (1 << bit)) != 0;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskDifference(
|
|
D3D10_STATE_BLOCK_MASK* pA,
|
|
D3D10_STATE_BLOCK_MASK* pB,
|
|
D3D10_STATE_BLOCK_MASK* pResult) {
|
|
if (!pA || !pB || !pResult)
|
|
return E_INVALIDARG;
|
|
|
|
auto a = reinterpret_cast<const BYTE*>(pA);
|
|
auto b = reinterpret_cast<const BYTE*>(pB);
|
|
auto r = reinterpret_cast<BYTE*>(pResult);
|
|
|
|
for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++)
|
|
r[i] = a[i] ^ b[i];
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskIntersect(
|
|
D3D10_STATE_BLOCK_MASK* pA,
|
|
D3D10_STATE_BLOCK_MASK* pB,
|
|
D3D10_STATE_BLOCK_MASK* pResult) {
|
|
if (!pA || !pB || !pResult)
|
|
return E_INVALIDARG;
|
|
|
|
auto a = reinterpret_cast<const BYTE*>(pA);
|
|
auto b = reinterpret_cast<const BYTE*>(pB);
|
|
auto r = reinterpret_cast<BYTE*>(pResult);
|
|
|
|
for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++)
|
|
r[i] = a[i] & b[i];
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE D3D10StateBlockMaskUnion(
|
|
D3D10_STATE_BLOCK_MASK* pA,
|
|
D3D10_STATE_BLOCK_MASK* pB,
|
|
D3D10_STATE_BLOCK_MASK* pResult) {
|
|
if (!pA || !pB || !pResult)
|
|
return E_INVALIDARG;
|
|
|
|
auto a = reinterpret_cast<const BYTE*>(pA);
|
|
auto b = reinterpret_cast<const BYTE*>(pB);
|
|
auto r = reinterpret_cast<BYTE*>(pResult);
|
|
|
|
for (size_t i = 0; i < sizeof(D3D10_STATE_BLOCK_MASK); i++)
|
|
r[i] = a[i] | b[i];
|
|
return S_OK;
|
|
}
|
|
|
|
}
|