Skip to content

Commit

Permalink
Merge pull request #13636 from hrydgard/reinterpret-framebuffer-formats
Browse files Browse the repository at this point in the history
Reinterpret framebuffer formats as needed. Outrun reflections partial fix
  • Loading branch information
hrydgard authored Nov 8, 2020
2 parents 614540a + d81522a commit ee46629
Show file tree
Hide file tree
Showing 45 changed files with 773 additions and 310 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,8 @@ set(GPU_SOURCES
GPU/Common/DrawEngineCommon.h
GPU/Common/PresentationCommon.cpp
GPU/Common/PresentationCommon.h
GPU/Common/ReinterpretFramebuffer.cpp
GPU/Common/ReinterpretFramebuffer.h
GPU/Common/ShaderId.cpp
GPU/Common/ShaderId.h
GPU/Common/ShaderUniforms.cpp
Expand Down
1 change: 1 addition & 0 deletions Common/Common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@
<ClInclude Include="Data\Collections\ConstMap.h" />
<ClInclude Include="Data\Collections\FixedSizeQueue.h" />
<ClInclude Include="Data\Collections\Hashmaps.h" />
<ClInclude Include="Data\Collections\Slice.h" />
<ClInclude Include="Data\Collections\ThreadSafeList.h" />
<ClInclude Include="Data\Collections\TinySet.h" />
<ClInclude Include="Data\Color\RGBAUtil.h" />
Expand Down
5 changes: 4 additions & 1 deletion Common/Common.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@
<ClInclude Include="GPU\ShaderWriter.h">
<Filter>GPU</Filter>
</ClInclude>
<ClInclude Include="Data\Collections\Slice.h">
<Filter>Data\Collections</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
Expand Down Expand Up @@ -850,4 +853,4 @@
<Filter>Math\fast</Filter>
</None>
</ItemGroup>
</Project>
</Project>
48 changes: 48 additions & 0 deletions Common/Data/Collections/Slice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#pragma once

#include <vector>

// Like a const begin/end pair, just more convenient to use (and can only be used for linear array data).
// Inspired by Rust's slices and Google's StringPiece.
template <class T>
struct Slice {
// View some memory as a slice.
Slice(const T *data, size_t size) : data_(data), size_(size) {}

// Intentionally non-explicit.
// View a const array as a slice.
template<size_t N>
Slice(const T(&data)[N]) : data_(data), size_(N) {}

// Intentionally non-explicit.
// View a const array as a slice.
Slice(const std::vector<T> &data) : data_(data.data()), size_(data.size()) {}

const T &operator[](size_t index) const {
return data_[index];
}

size_t size() const {
return size_;
}

// "Iterators"
const T *begin() const {
return data_;
}
const T *end() const {
return data_ + size_;
}

static Slice empty() {
return Slice<T>(nullptr, 0);
}

bool is_empty() const {
return size_ == 0;
}

private:
const T *data_;
size_t size_;
};
33 changes: 24 additions & 9 deletions Common/GPU/D3D11/thin3d_d3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ InputLayout *D3D11DrawContext::CreateInputLayout(const InputLayoutDesc &desc) {
return inputLayout;
}

class D3D11ShaderModule;

class D3D11Pipeline : public Pipeline {
public:
~D3D11Pipeline() {
Expand All @@ -680,7 +682,7 @@ class D3D11Pipeline : public Pipeline {
if (dynamicUniforms)
dynamicUniforms->Release();
}
bool RequiresBuffer() {
bool RequiresBuffer() override {
return true;
}

Expand All @@ -694,6 +696,8 @@ class D3D11Pipeline : public Pipeline {
ID3D11GeometryShader *gs = nullptr;
D3D11_PRIMITIVE_TOPOLOGY topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;

std::vector<D3D11ShaderModule *> shaderModules;

size_t dynamicUniformsSize = 0;
ID3D11Buffer *dynamicUniforms = nullptr;
};
Expand Down Expand Up @@ -966,7 +970,9 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
dPipeline->raster = (D3D11RasterState *)desc.raster;
dPipeline->blend->AddRef();
dPipeline->depth->AddRef();
dPipeline->input->AddRef();
if (dPipeline->input) {
dPipeline->input->AddRef();
}
dPipeline->raster->AddRef();
dPipeline->topology = primToD3D11[(int)desc.prim];
if (desc.uniformDesc) {
Expand All @@ -983,6 +989,8 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
std::vector<D3D11ShaderModule *> shaders;
D3D11ShaderModule *vshader = nullptr;
for (auto iter : desc.shaders) {
iter->AddRef();

D3D11ShaderModule *module = (D3D11ShaderModule *)iter;
shaders.push_back(module);
switch (module->GetStage()) {
Expand All @@ -998,6 +1006,7 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
break;
}
}
dPipeline->shaderModules = shaders;

if (!vshader) {
// No vertex shader - no graphics
Expand All @@ -1006,11 +1015,15 @@ Pipeline *D3D11DrawContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
}

// Can finally create the input layout
auto &inputDesc = dPipeline->input->desc;
const std::vector<D3D11_INPUT_ELEMENT_DESC> &elements = dPipeline->input->elements;
HRESULT hr = device_->CreateInputLayout(elements.data(), (UINT)elements.size(), vshader->byteCode_.data(), vshader->byteCode_.size(), &dPipeline->il);
if (!SUCCEEDED(hr)) {
Crash();
if (dPipeline->input) {
auto &inputDesc = dPipeline->input->desc;
const std::vector<D3D11_INPUT_ELEMENT_DESC> &elements = dPipeline->input->elements;
HRESULT hr = device_->CreateInputLayout(elements.data(), (UINT)elements.size(), vshader->byteCode_.data(), vshader->byteCode_.size(), &dPipeline->il);
if (!SUCCEEDED(hr)) {
Crash();
}
} else {
dPipeline->il = nullptr;
}
return dPipeline;
}
Expand Down Expand Up @@ -1081,8 +1094,10 @@ void D3D11DrawContext::ApplyCurrentState() {
curTopology_ = curPipeline_->topology;
}

int numVBs = (int)curPipeline_->input->strides.size();
context_->IASetVertexBuffers(0, 1, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_);
if (curPipeline_->input) {
int numVBs = (int)curPipeline_->input->strides.size();
context_->IASetVertexBuffers(0, numVBs, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_);
}
if (dirtyIndexBuffer_) {
context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R16_UINT, nextIndexBufferOffset_);
dirtyIndexBuffer_ = false;
Expand Down
29 changes: 21 additions & 8 deletions Common/GPU/OpenGL/thin3d_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ class OpenGLPipeline : public Pipeline {
bool LinkShaders();

bool RequiresBuffer() override {
return inputLayout->RequiresBuffer();
return inputLayout && inputLayout->RequiresBuffer();
}

GLuint prim = 0;
Expand Down Expand Up @@ -1051,7 +1051,7 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
ERROR_LOG(G3D, "Invalid primitive type");
return nullptr;
}
if (!desc.depthStencil || !desc.blend || !desc.raster || !desc.inputLayout) {
if (!desc.depthStencil || !desc.blend || !desc.raster) {
ERROR_LOG(G3D, "Incomplete prim desciption");
return nullptr;
}
Expand Down Expand Up @@ -1081,7 +1081,9 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
pipeline->depthStencil->AddRef();
pipeline->blend->AddRef();
pipeline->raster->AddRef();
pipeline->inputLayout->AddRef();
if (pipeline->inputLayout) {
pipeline->inputLayout->AddRef();
}
return pipeline;
} else {
ERROR_LOG(G3D, "Failed to create pipeline - shaders failed to link");
Expand Down Expand Up @@ -1219,20 +1221,25 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
void OpenGLContext::Draw(int vertexCount, int offset) {
_dbg_assert_msg_(curVBuffers_[0], "Can't call Draw without a vertex buffer");
ApplySamplers();
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
if (curPipeline_->inputLayout) {
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
}
renderManager_.Draw(curPipeline_->prim, offset, vertexCount);
}

void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
_dbg_assert_msg_(curVBuffers_[0], "Can't call DrawIndexed without a vertex buffer");
_dbg_assert_msg_(curIBuffer_, "Can't call DrawIndexed without an index buffer");
ApplySamplers();
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
if (curPipeline_->inputLayout) {
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
}
renderManager_.BindIndexBuffer(curIBuffer_->buffer_);
renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t)));
}

void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
_assert_(curPipeline_->inputLayout);
int stride = curPipeline_->inputLayout->stride;
size_t dataSize = stride * vertexCount;

Expand All @@ -1242,7 +1249,9 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
size_t offset = frameData.push->Push(vdata, dataSize, &buf);

ApplySamplers();
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset);
if (curPipeline_->inputLayout) {
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset);
}
renderManager_.Draw(curPipeline_->prim, 0, vertexCount);
}

Expand Down Expand Up @@ -1273,7 +1282,7 @@ OpenGLInputLayout::~OpenGLInputLayout() {
void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) {
// TODO: This is only accurate if there's only one stream. But whatever, for now we
// never use multiple streams anyway.
stride = (GLsizei)desc.bindings[0].stride;
stride = desc.bindings.empty() ? 0 : (GLsizei)desc.bindings[0].stride;

std::vector<GLRInputLayout::Entry> entries;
for (auto &attr : desc.attributes) {
Expand Down Expand Up @@ -1310,7 +1319,11 @@ void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) {

entries.push_back(entry);
}
inputLayout_ = render_->CreateInputLayout(entries);
if (!entries.empty()) {
inputLayout_ = render_->CreateInputLayout(entries);
} else {
inputLayout_ = nullptr;
}
}

Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
Expand Down
10 changes: 5 additions & 5 deletions Common/GPU/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
fragColor0 = "fragColor0";
fragColor1 = "fragColor1";
texture = "texture";
texelFetch = nullptr;
bitwiseOps = false;
texelFetch = "texelFetch";
bitwiseOps = true;
lastFragData = nullptr;
gles = false;
gles = true;
forceMatrix4x4 = true;
glslES30 = true;
bitwiseOps = true;
texelFetch = "texelFetch";
break;
case GLSL_VULKAN:
Expand Down Expand Up @@ -67,14 +66,15 @@ void ShaderLanguageDesc::Init(ShaderLanguage lang) {
bitwiseOps = lang == HLSL_D3D11;
framebufferFetchExtension = nullptr;
gles = false;
glslES30 = true;
glslES30 = true; // Hm, D3D9 too?
glslVersionNumber = 0;
lastFragData = nullptr;
texture = "texture";
texelFetch = "texelFetch";
forceMatrix4x4 = false;
coefsFromBuffers = true;
vsOutPrefix = "Out.";
viewportYSign = "-";
break;
}
}
Expand Down
31 changes: 30 additions & 1 deletion Common/GPU/Shader.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#pragma once

#include <vector>
#include <cstdint>
#include <cstddef> // for size_t

// GLSL_1xx and GLSL_3xx each cover a lot of sub variants. All the little quirks
// that differ are covered in ShaderLanguageDesc.
// Defined as a bitmask so stuff like GetSupportedShaderLanguages can return combinations.
Expand Down Expand Up @@ -41,12 +45,37 @@ struct ShaderLanguageDesc {
const char *lastFragData = nullptr;
const char *framebufferFetchExtension = nullptr;
const char *vsOutPrefix = "";
bool glslES30 = false;
const char *viewportYSign = "";
bool glslES30 = false; // really glslES30Features. TODO: Clean this up.
bool bitwiseOps = false;
bool forceMatrix4x4 = false;
bool coefsFromBuffers = false;
};

enum class UniformType : int8_t {
FLOAT1,
FLOAT2,
FLOAT3,
FLOAT4,
MATRIX4X4,
};

// Describe uniforms intricately enough that we can support them on all backends.
// This will generate a uniform struct on the newer backends and individual uniforms on the older ones.
struct UniformDesc {
const char *name; // For GL
int16_t vertexReg; // For D3D
int16_t fragmentReg; // For D3D
UniformType type;
int16_t offset;
// TODO: Support array elements etc.
};

struct UniformBufferDesc {
size_t uniformBufferSize;
std::vector<UniformDesc> uniforms;
};

// For passing error messages from shader compilation (and other critical issues) back to the host.
// This can run on any thread - be aware!
// TODO: See if we can find a less generic name for this.
Expand Down
Loading

0 comments on commit ee46629

Please sign in to comment.