dxvk/src/d3d9/d3d9_shader.h

216 lines
5.5 KiB
C++

#pragma once
#include "d3d9_resource.h"
#include "../dxso/dxso_module.h"
#include "d3d9_util.h"
#include "d3d9_mem.h"
#include <array>
namespace dxvk {
/**
* \brief Common shader object
*
* Stores the compiled SPIR-V shader and the SHA-1
* hash of the original DXBC shader, which can be
* used to identify the shader.
*/
class D3D9CommonShader {
public:
D3D9CommonShader();
D3D9CommonShader(
D3D9DeviceEx* pDevice,
VkShaderStageFlagBits ShaderStage,
const DxvkShaderKey& Key,
const DxsoModuleInfo* pDxbcModuleInfo,
const void* pShaderBytecode,
const DxsoAnalysisInfo& AnalysisInfo,
DxsoModule* pModule);
Rc<DxvkShader> GetShader() const {
return m_shader;
}
std::string GetName() const {
return m_shader->debugName();
}
const DxsoIsgn& GetIsgn() const {
return m_isgn;
}
const DxsoShaderMetaInfo& GetMeta() const { return m_meta; }
const DxsoDefinedConstants& GetConstants() const { return m_constants; }
D3D9ShaderMasks GetShaderMask() const { return D3D9ShaderMasks{ m_usedSamplers, m_usedRTs }; }
const DxsoProgramInfo& GetInfo() const { return m_info; }
uint32_t GetMaxDefinedConstant() const { return m_maxDefinedConst; }
private:
DxsoIsgn m_isgn;
uint32_t m_usedSamplers;
uint32_t m_usedRTs;
DxsoProgramInfo m_info;
DxsoShaderMetaInfo m_meta;
DxsoDefinedConstants m_constants;
uint32_t m_maxDefinedConst;
Rc<DxvkShader> m_shader;
};
/**
* \brief Common shader interface
*
* Implements methods for all D3D11*Shader
* interfaces and stores the actual shader
* module object.
*/
template <typename Base>
class D3D9Shader : public D3D9DeviceChild<Base> {
public:
D3D9Shader(
D3D9DeviceEx* pDevice,
D3D9MemoryAllocator* pAllocator,
const D3D9CommonShader& CommonShader,
const void* pShaderBytecode,
uint32_t BytecodeLength)
: D3D9DeviceChild<Base>( pDevice )
, m_shader ( CommonShader )
, m_bytecodeLength ( BytecodeLength ) {
m_bytecode = pAllocator->Alloc(BytecodeLength);
m_bytecode.Map();
std::memcpy(m_bytecode.Ptr(), pShaderBytecode, BytecodeLength);
m_bytecode.Unmap();
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr)
return E_POINTER;
*ppvObject = nullptr;
if (riid == __uuidof(IUnknown)
|| riid == __uuidof(Base)) {
*ppvObject = ref(this);
return S_OK;
}
if (logQueryInterfaceError(__uuidof(Base), riid)) {
Logger::warn("D3D9Shader::QueryInterface: Unknown interface query");
Logger::warn(str::format(riid));
}
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE GetFunction(void* pOut, UINT* pSizeOfData) {
if (pSizeOfData == nullptr)
return D3DERR_INVALIDCALL;
if (pOut == nullptr) {
*pSizeOfData = m_bytecodeLength;
return D3D_OK;
}
m_bytecode.Map();
uint32_t copyAmount = std::min(*pSizeOfData, m_bytecodeLength);
std::memcpy(pOut, m_bytecode.Ptr(), copyAmount);
m_bytecode.Unmap();
return D3D_OK;
}
const D3D9CommonShader* GetCommonShader() const {
return &m_shader;
}
private:
D3D9CommonShader m_shader;
D3D9Memory m_bytecode;
uint32_t m_bytecodeLength;
};
// Needs their own classes and not usings for forward decl.
class D3D9VertexShader final : public D3D9Shader<IDirect3DVertexShader9> {
public:
D3D9VertexShader(
D3D9DeviceEx* pDevice,
D3D9MemoryAllocator* pAllocator,
const D3D9CommonShader& CommonShader,
const void* pShaderBytecode,
uint32_t BytecodeLength)
: D3D9Shader<IDirect3DVertexShader9>( pDevice, pAllocator, CommonShader, pShaderBytecode, BytecodeLength ) { }
};
class D3D9PixelShader final : public D3D9Shader<IDirect3DPixelShader9> {
public:
D3D9PixelShader(
D3D9DeviceEx* pDevice,
D3D9MemoryAllocator* pAllocator,
const D3D9CommonShader& CommonShader,
const void* pShaderBytecode,
uint32_t BytecodeLength)
: D3D9Shader<IDirect3DPixelShader9>( pDevice, pAllocator, CommonShader, pShaderBytecode, BytecodeLength ) { }
};
/**
* \brief Shader module set
*
* Some applications may compile the same shader multiple
* times, so we should cache the resulting shader modules
* and reuse them rather than creating new ones. This
* class is thread-safe.
*/
class D3D9ShaderModuleSet : public RcObject {
public:
void GetShaderModule(
D3D9DeviceEx* pDevice,
D3D9CommonShader* pShaderModule,
uint32_t* pLength,
VkShaderStageFlagBits ShaderStage,
const DxsoModuleInfo* pDxbcModuleInfo,
const void* pShaderBytecode);
private:
dxvk::mutex m_mutex;
std::unordered_map<
DxvkShaderKey,
D3D9CommonShader,
DxvkHash, DxvkEq> m_modules;
};
template<typename T>
const D3D9CommonShader* GetCommonShader(const T& pShader) {
return pShader != nullptr ? pShader->GetCommonShader() : nullptr;
}
}